#include "sqlconnpool.h"
using namespace std;
//数据库连接池的构造函数
SqlConnPool::SqlConnPool()
{
    //初始化数据库连接池的当前使用数量是0
    useCount_ = 0;
    //初始化数据库连接池的空闲数量是0
    freeCount_ = 0;
}
//数据库连接池的单例模式，返回数据库连接池的实例
SqlConnPool* SqlConnPool::Instance()
{
    //创建一个数据库连接池的实例
    static SqlConnPool pool;
    //返回数据库连接池的地址
    return &pool;
}
//数据库连接池的初始化函数
void SqlConnPool::Init(const char* host,int port,const char* user,const char* pwd,const char* dbName,int connSize = 10)
{
    //断言连接数量是否大于0
    assert(connSize > 0);
    //初始化数据库连接池的最大连接数量
    for(int i = 0;i < connSize;i++)
    {
        //创建一个数据库连接
        MYSQL* sql = nullptr;
        //初始化数据库连接
        sql = mysql_init(sql);
        //如果初始化失败，就打印错误日志
        if(!sql)
        {
            //打印错误日志
            LOG_ERROR("MySql init error!");
            //断言失败的情况
            assert(sql);
        }
        //数据库连接初始化成功，连接数据库
        sql = mysql_real_connect(sql,host,user,pwd,dbName,port,nullptr,0);
        //如果数据库连接失败
        if(!sql)
        {
            //打印错误日志
            LOG_ERROR("MySql connect error!");
        }
        //数据库连接成功，将连接放入连接队列
        connQue_.push(sql);
    }
    //初始化数据库连接池的最大连接数量
    MAX_CONN_ = connSize;
    //初始化信号量，初始值是最大连接数量
    sem_init(&semId_,0,MAX_CONN_);
}
//数据库连接池的获取连接函数
MYSQL* SqlConnPool::GetConn()
{
    //定义一个数据库连接指针
    MYSQL* sql = nullptr;
    //如果连接队列为空
    if(connQue_.empty())
    {
        //打印警告日志
        LOG_WARN("SqlConnPool busy!");
        //返回空指针
        return nullptr;
    }
    //等待信号量，确保有可用连接
    sem_wait(&semId_);
    {
        //获取互斥锁，保证线程安全
        lock_guard<mutex> locker(mtx_);
        //从连接队列中获取一个连接
        sql = connQue_.front();
        //从连接队列中移除一个连接
        connQue_.pop();
    }
    //返回获取到的数据库连接
    return sql;
}
//连接释放函数，用于将使用完毕的数据库连接归还到线程池中，增加可用连接数量
void SqlConnPool::FreeConn(MYSQL* sql)
{
    //确保传入的连接指针不为空
    assert(sql);
    //获取互斥锁，保证线程安全
    lock_guard<mutex> locker(mtx_);
    //将连接放回连接队列
    connQue_.push(sql);
    //释放信号量，增加可用连接数量
    sem_post(&semId_);
}
//关闭数据库连接池
void SqlConnPool::ClosePool()
{
    //获取互斥锁，保证线程安全
    lock_guard<mutex> locker(mtx_);
    //循环判断数据库连接池是否为空
    while(!connQue_.empty())
    {
        //获取连接池的顶部的连接
        auto sql = connQue_.front();
        //从连接池中移除一个连接
        connQue_.pop();
        //将新获取的连接关闭
        mysql_close(sql);
    }
    //关闭数据库连接库
    mysql_library_end();
}
//获取数据库连接池的空闲连接数量
int SqlConnPool::GetFreeConnCount()
{
    lock_guard<mutex> locker(mtx_);
    return connQue_.size();
}
//数据库连接池的析构函数
SqlConnPool::~SqlConnPool()
{
    ClosePool();
}